package com.founder.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.founder.config.WebConfig;
import com.founder.core.dao.PayOrderRespository;
import com.founder.core.domain.PayOrder;
import com.founder.core.enumm.TradeEnum;
import com.founder.core.log.MyLog;
import com.founder.core.utils.AmountUtil;
import com.founder.core.utils.PayDigestUtil;
import com.founder.core.utils.PayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Service
public class GatewayService {

    private final MyLog _log = MyLog.getLog(GatewayService.class);

    @Autowired
    WebConfig webConfig;

    @Autowired
    ExtendService extendService;

    @Autowired
    PayOrderRespository payOrderRespository;

    /**
     * 统一下单
     * @param mchId
     * @param orderNo
     * @param totalAmount
     * @param subject
     * @param storeId
     * @param timeOutExpress
     * @param clientIp
     * @param hostName
     * @return 返回值状态码code=0标识成功
     */
    public Map<String, Object> precreate(String mchId, String channelId, String orderNo, BigDecimal totalAmount, String subject, String storeId, String timeOutExpress, String clientIp, String hostName){
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("code", "0");
        result.put("msg", "success");

        if (StringUtils.isEmpty(mchId)) {
            result.put("code", "1");
            result.put("msg", "参数商户号不能为空");
            _log.error("参数商户号不能为空");
            return result;
        }
        _log.info("打印参数：{}", mchId);

        if (StringUtils.isEmpty(channelId)) {
            result.put("code", "2");
            result.put("msg", "参数支付渠道号不能为空");
            _log.error("参数支付渠道号不能为空");
            return result;
        }
        _log.info("打印参数：{}", channelId);

        if (StringUtils.isEmpty(orderNo)) {
            result.put("code", "3");
            result.put("msg", "参数订单号不能为空");
            _log.error("参数订单号不能为空");
            return result;
        }
        _log.info("打印参数：{}", orderNo);

        if (totalAmount.compareTo(new BigDecimal(0.0)) < 1) {
            result.put("code", "4");
            result.put("msg", "参数支付金额不能小于等于0");
            _log.error("参数支付金额不能小于等于0");
            return result;
        }
        _log.info("打印参数：{}", totalAmount);

        _log.info("查询订单{}是否已经存在", orderNo);
        if (payOrderRespository.existsById(orderNo)){
            result.put("code", "5");
            result.put("msg", "订单号已存在.");
            _log.error("订单号{}已存在",orderNo);
            return result;
        }

        JSONObject paramMap = new JSONObject();
        paramMap.put("mchId", mchId);                               // 商户ID
        paramMap.put("mchOrderNo", orderNo);     // 商户订单号
        paramMap.put("channelId", channelId);
        paramMap.put("amount", AmountUtil.convertDollar2Cent(String.valueOf(totalAmount)));   // 支付金额,单位分
        paramMap.put("currency", webConfig.getCurrency());                            // 币种, cny-人民币
        paramMap.put("clientIp", clientIp);                 // 用户地址,微信H5支付时要真实的
        paramMap.put("device", webConfig.getDevice());                              // 设备
        paramMap.put("subject", subject);
        paramMap.put("body", subject);
        paramMap.put("notifyUrl", webConfig.getNotify_url());                       // 回调URL
        paramMap.put("param1", "");                                 // 扩展参数1
        paramMap.put("param2", "");                                 // 扩展参数2
        if ("WX_NATIVE".equals(channelId)){
            paramMap.put("extra", "{\"productId\": \"00000000\"}");
        }
        String reqSign = PayDigestUtil.getSign(paramMap, webConfig.getReq_key());
        paramMap.put("sign", reqSign);                              // 签名
        String reqData = "params=" + paramMap.toJSONString();
        _log.info("请求支付中心下单接口,请求数据:" + reqData);
        String url = webConfig.getBase_url() + "/pay/create_order?";
        String retData = PayUtil.call4Post(url + reqData);
        _log.info("请求支付中心下单接口,响应数据:" + retData);
        Map retMap = JSON.parseObject(retData);
        if("SUCCESS".equals(retMap.get("retCode")) && "SUCCESS".equalsIgnoreCase(retMap.get("resCode").toString())) {
            result.put("code", "0");
            result.put("qr_code", retMap.get("codeUrl"));
            result.put("trade_no", retMap.get("payOrderId"));
        } else {
            result.put("code", "6");
            result.put("msg", "统一下单失败.");
            _log.error("统一下单失败{}",orderNo);
            return result;
        }

        return result;
    }

    /**
     * 退费
     * @param orderNo
     * @param refundAmount
     * @param refundReason
     * @return 返回值状态码code=0标识成功
     */
    public Map<String, Object> refund(String orderNo, BigDecimal refundAmount, String refundReason){
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("code", "0");
        result.put("order_no", orderNo);
        result.put("msg", "success");

        if (StringUtils.isEmpty(orderNo)) {
            result.put("code", "1");
            result.put("msg", "参数退费订单号不能为空");
            _log.error("参数退费订单号不能为空");
            return result;
        }
        _log.info("打印参数：{}", orderNo);

        Optional<PayOrder> optional = payOrderRespository.findById(orderNo);
        PayOrder order = null;
        if (!optional.isPresent()){
            if (webConfig.getExecute_sync()){
                _log.info("配置从分库同步订单");
                order = extendService.trans("10000000", orderNo);
            }
            if (order == null) {
                result.put("code", "2");
                result.put("msg", "退费订单不存在.订单号：" + orderNo);
                _log.error("退费订单不存在.订单号：{}.", orderNo);
                return result;
            }
        } else {
            order = optional.get();
            _log.info("订单存在：{}", JSON.toJSONString(order));
        }

        String mchId = order.getMchId();
        String channelId = order.getChannelId();
        String client_ip = order.getClientIp();
        String channelUser = order.getChannelOrderNo();
        _log.info("通过订单反查商户号：{}，渠道ID：{}，退费金额：{}。",mchId,channelId,refundAmount);

        if (StringUtils.isEmpty(mchId)) {
            result.put("code", "3");
            result.put("msg", "【退费】参数商户号不能为空");
            _log.error("【退费】参数商户号不能为空");
            return result;
        }

        if (StringUtils.isEmpty(channelId)) {
            result.put("code", "4");
            result.put("msg", "【退费】参数支付渠道号不能为空");
            _log.error("【退费】参数支付渠道号不能为空");
            return result;
        }

        JSONObject paramMap = new JSONObject();
        paramMap.put("mchId", mchId);                               // 商户ID
        paramMap.put("mchOrderNo", orderNo);     // 商户订单号
        paramMap.put("channelId", channelId);
        paramMap.put("amount", AmountUtil.convertDollar2Cent(refundAmount.toString()));  // 退款金额 转为分
        paramMap.put("currency", webConfig.getCurrency());                            // 币种, cny-人民币
        paramMap.put("clientIp", client_ip);                 // 用户地址,微信H5支付时要真实的
        paramMap.put("device", webConfig.getDevice());                              // 设备
        paramMap.put("subject", refundReason);
        paramMap.put("body", refundReason);
        paramMap.put("notifyUrl", webConfig.getNotify_url());                       // 回调URL
        paramMap.put("param1", "");                                 // 扩展参数1
        paramMap.put("param2", "");                                 // 扩展参数2
        paramMap.put("channelUser", channelUser);  // 微信openId:oIkQuwhPgPUgl-TvQ48_UUpZUwMs(丁志伟)
        paramMap.put("payOrderId", orderNo);
        paramMap.put("refundType","0");//退

        String reqSign = PayDigestUtil.getSign(paramMap, webConfig.getReq_key());
        paramMap.put("sign", reqSign);                              // 签名
        String reqData = "params=" + paramMap.toJSONString();
        _log.info("请求支付中心退费接口,请求数据:" + reqData);
        String url = webConfig.getBase_url() + "/refund/create_order?";
        String retData = PayUtil.call4Post(url + reqData);
        _log.info("请求支付中心退费接口,响应数据:" + result);
        Map retMap = JSON.parseObject(retData);
        if("SUCCESS".equals(retMap.get("retCode")) && "SUCCESS".equalsIgnoreCase(retMap.get("resCode").toString())) {
            result.put("code", "0");
        } else {
            result.put("code", "5");
            result.put("msg", "订单【退费】失败.");
            _log.error("订单【退费】失败{}.",orderNo);
            return result;
        }

        return result;
    }

    /**
     * 撤销
     * @param orderNo
     * @return 返回值状态码code=0标识成功
     */
    public Map<String, Object> cancel(String orderNo){
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("code", "0");
        result.put("order_no", orderNo);
        result.put("msg", "success");

        if (StringUtils.isEmpty(orderNo)) {
            result.put("code", "1");
            result.put("msg", "【撤销】参数订单号不能为空");
            _log.error("【撤销】参数订单号不能为空");
            return result;
        }
        _log.info("打印参数：{}", orderNo);

        Optional<PayOrder> optional = payOrderRespository.findById(orderNo);
        PayOrder order = null;
        if (!optional.isPresent()){
            if (webConfig.getExecute_sync()){
                _log.info("配置从分库同步订单");
                order = extendService.trans("10000000", orderNo);
            }
            if (order == null) {
                result.put("code", "2");
                result.put("msg", "撤销订单不存在.订单号：" + orderNo);
                _log.error("撤销订单不存在.订单号：{}.",orderNo);
                return result;
            }
        } else {
            order = optional.get();
            _log.info("订单存在：{}", JSON.toJSONString(order));
        }

        String mchId = order.getMchId();
        String channelId = order.getChannelId();
        Long refundAmount = order.getAmount();
        String client_ip = order.getClientIp();
        String channelUser = order.getChannelOrderNo();
        _log.info("通过订单反查商户号：{}，渠道ID：{}，撤销金额：{}。",mchId,channelId,refundAmount);

        if (StringUtils.isEmpty(mchId)) {
            result.put("code", "3");
            result.put("msg", "【撤销】参数商户号不能为空");
            _log.error("【撤销】参数商户号不能为空");
            return result;
        }

        if (StringUtils.isEmpty(channelId)) {
            result.put("code", "4");
            result.put("msg", "【撤销】参数支付渠道号不能为空");
            _log.error("【撤销】参数支付渠道号不能为空");
            return result;
        }

        JSONObject paramMap = new JSONObject();
        paramMap.put("mchId", mchId);                               // 商户ID
        paramMap.put("mchOrderNo", orderNo);     // 商户订单号
        paramMap.put("channelId", channelId);
        paramMap.put("amount", refundAmount);  // 退款金额
        paramMap.put("currency", webConfig.getCurrency());                            // 币种, cny-人民币
        paramMap.put("clientIp", client_ip);                 // 用户地址,微信H5支付时要真实的
        paramMap.put("device", webConfig.getDevice());                              // 设备
        paramMap.put("subject", "交易撤销");
        paramMap.put("body", "交易撤销");
        paramMap.put("notifyUrl", webConfig.getNotify_url());                       // 回调URL
        paramMap.put("param1", "");                                 // 扩展参数1
        paramMap.put("param2", "");                                 // 扩展参数2
        paramMap.put("channelUser", channelUser);  // 微信openId:oIkQuwhPgPUgl-TvQ48_UUpZUwMs(丁志伟)
        paramMap.put("payOrderId", orderNo);
        paramMap.put("refundType","1");//撤销

        String reqSign = PayDigestUtil.getSign(paramMap, webConfig.getReq_key());
        paramMap.put("sign", reqSign);                              // 签名
        String reqData = "params=" + paramMap.toJSONString();
        _log.info("请求支付中心撤销接口,请求数据:" + reqData);
        String url = webConfig.getBase_url() + "/cancel/create_order?";
        String retData = PayUtil.call4Post(url + reqData);
        _log.info("请求支付中心撤销接口,响应数据:" + result);
        Map retMap = JSON.parseObject(retData);
        if("SUCCESS".equals(retMap.get("retCode")) && "SUCCESS".equalsIgnoreCase(retMap.get("resCode").toString())) {
            result.put("code", "0");
        } else {
            result.put("code", "5");
            result.put("msg", "订单撤销失败.");
            _log.error("订单撤销失败{}.",orderNo);
            return result;
        }

        return result;
    }

    /**
     * 查询
     * @param mchId
     * @param channelId
     * @param orderNo
     * @return
     */
    public Map<String, Object> query(String mchId, String channelId, String orderNo){
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("code", "0");
        result.put("order_no", orderNo);
        result.put("msg", "success");

        if (StringUtils.isEmpty(orderNo)) {
            result.put("code", "99");
            result.put("msg", "参数订单号不能为空");
            _log.error("参数订单号不能为空");
            return result;
        }
        _log.info("打印参数：{}", orderNo);

        if (StringUtils.isEmpty(mchId) || StringUtils.isEmpty(channelId)) {
            _log.info("传入的商户号为空,通过订单号反查");

            Optional<PayOrder> optional = payOrderRespository.findById(orderNo);
            if (!optional.isPresent()){
                result.put("code", "98");
                result.put("msg", "订单不存在.订单号：" + orderNo);
                _log.error("订单不存在.订单号：{}.",orderNo);
                return result;
            }

            PayOrder payOrder = optional.get();
            mchId = payOrder.getMchId();
            channelId = payOrder.getChannelId();
            _log.info("通过订单反查商户号：{}，渠道ID：{}。",mchId,channelId);
        }

        if (StringUtils.isEmpty(mchId)) {
            result.put("code", "100");
            result.put("msg", "参数商户号不能为空");
            _log.error("参数商户号不能为空");
            return result;
        }
        _log.info("打印参数：{}", mchId);

        if (StringUtils.isEmpty(channelId)) {
            result.put("code", "100");
            result.put("msg", "参数支付渠道号不能为空");
            _log.error("参数支付渠道号不能为空");
            return result;
        }
        _log.info("打印参数：{}", channelId);

        JSONObject paramMap = new JSONObject();
        paramMap.put("mchId", mchId);                               // 商户ID
        paramMap.put("channelId", channelId);
        paramMap.put("mchOrderNo", orderNo);                     // 商户订单号
        paramMap.put("payOrderId", orderNo);                     // 支付订单号
        paramMap.put("executeNotify", webConfig.getExecute_notify());  // 是否执行回调,true或false,如果为true当订单状态为支付成功(2)时,支付中心会再次回调一次业务系统
        paramMap.put("executeQuery", webConfig.getExecute_query()); //查询时是否更新订单状态

        String reqSign = PayDigestUtil.getSign(paramMap, webConfig.getReq_key());
        paramMap.put("sign", reqSign);   // 签名
        String reqData = "params=" + paramMap.toJSONString();
        _log.info("请求支付中心查单接口,请求数据:{}", reqData);
        String url = webConfig.getBase_url() + "/query/create_order?";
        String retData = PayUtil.call4Post(url + reqData);
        _log.info("请求支付中心查单接口,响应数据:{}", retData);
        Map retMap = JSON.parseObject(retData);
        if("SUCCESS".equals(retMap.get("retCode")) && "SUCCESS".equalsIgnoreCase(retMap.get("resCode").toString())) {
            String trade_status = retMap.get("tradeStatus").toString();
            TradeEnum tradeEnum = TradeEnum.getObject(trade_status);
            _log.info("订单状态：{},{}." + trade_status, tradeEnum.getCode(),tradeEnum.getMessage());

            if ("SUCCESS".equals(tradeEnum.getCode())){
                result.put("code", "0");
                result.put("order_no", orderNo);
                result.put("msg", "微信订单支付成功");
                result.put("trade_status", "1");
            } else if ("TRADE_SUCCESS".equals(tradeEnum.getCode())){
                result.put("code", "0");
                result.put("order_no", orderNo);
                result.put("msg", "支付宝订单支付成功");
                result.put("trade_status", "1");
            } else {
                result.put("code", "98");
                result.put("msg", tradeEnum.getMessage());
                _log.info("查询订单成功{},{}.",orderNo,tradeEnum.getMessage());
                return result;
            }
        } else {
            result.put("code", "98");
            result.put("msg", "查询订单失败.");
            _log.error("查询订单失败{}.",orderNo);
            return result;
        }

        return result;
    }
}
